package org.dxy.domain.model.aggregate.impl;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.dxy.domain.command.productionLine.*;
import org.dxy.domain.event.DomainEvent;
import org.dxy.domain.event.productionLine.*;
import org.dxy.domain.model.aggregate.ProductionLine;
import org.dxy.domain.model.aggregate.WorkOrder;
import org.dxy.domain.model.aggregate.Workstation;
import org.dxy.domain.model.valobj.ProductionLineId;
import org.dxy.domain.model.valobj.WorkstationId;
import org.dxy.types.enums.LineStatusEnum;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

/**
 * @description: 产线聚合根实现类
 * @author: dxy 
 * @createTime: 2025/6/22 17:26 
 */
@Slf4j
@Getter
@Builder
public class ProductionLineAggRoot implements ProductionLine {

    private ProductionLineId productionLineId;       // 产线ID（聚合唯一标识）
    private String lineCode;
    private Long processRouteId;                     // 绑定的工艺路线ID
    private LineStatusEnum status;                   // 当前产线状态
    private List<Long> assignedWorkOrderIds;           // 当前分配的工单ID列表
    private List<WorkstationId> workstationIds;

    // === 事件集合 ===
    private final List<DomainEvent> domainEvents = new ArrayList<>();

    // === 事件相关方法 ===
    @Override
    public List<DomainEvent> getDomainEvents() {
        return Collections.unmodifiableList(domainEvents); // 返回一个 不可修改的视图
    }

    @Override
    public void addDomainEvent(DomainEvent event) {
        domainEvents.add(event);
    }

    @Override
    public void clearDomainEvents() {
        domainEvents.clear();
    }

    @Override
    public boolean hasDomainEvents() {
        return !domainEvents.isEmpty();
    }

    @Override
    public boolean hasNoDomainEvents() {
        return domainEvents.isEmpty();
    }

    // === 静态工厂方法 ===
    public static ProductionLine create(CreateProductionLineCommand command, Long productionLineId) {
        ProductionLineAggRoot productionLine = ProductionLineAggRoot.builder()
                .productionLineId(new ProductionLineId(productionLineId))
                .lineCode(command.lineCode())
                .status(LineStatusEnum.ENABLED)
                .build();

        ProductionLineCreatedEvent event = ProductionLineCreatedEvent.builder()
                .lineId(productionLineId)
                .build();
        productionLine.addDomainEvent(event);
        return productionLine;
    }

    // === 业务方法实现 ===
    @Override
    public ProductionLineStartedEvent start(StartProductionLineCommand command) {
        if (this.status == LineStatusEnum.STARTED) {
            log.error("产线已启动，忽略重复启动请求: lineId={}", productionLineId.getValue());
            throw new IllegalStateException("产线已处于启动状态");
        }
        this.status = LineStatusEnum.STARTED;
        return ProductionLineStartedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .build();
    }

    @Override
    public ProductionLinePausedEvent pause(PauseProductionLineCommand command) {
        if (this.status != LineStatusEnum.STARTED) {
            throw new IllegalStateException("仅可在运行中的产线执行暂停操作");
        }
        this.status = LineStatusEnum.PAUSED;
        return ProductionLinePausedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .build();
    }

    @Override
    public ProductionLineResumedEvent resume(ResumeProductionLineCommand command) {
        if (this.status != LineStatusEnum.PAUSED) {
            throw new IllegalStateException("仅可在暂停状态的产线执行恢复操作");
        }

        this.status = LineStatusEnum.STARTED;

        return ProductionLineResumedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .status(this.status.getKey())
                .build();
    }

    @Override
    public ProductionLineStoppedEvent stop(StopProductionLineCommand command) {
        if (this.status == LineStatusEnum.STOPPED) {
            throw new IllegalStateException("产线已处于停止状态");
        }
        
        this.status = LineStatusEnum.STOPPED;

        return ProductionLineStoppedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .status(this.status.getKey())
                .build();
    }

    @Override
    public ProductionLineRemovedEvent remove(RemoveProductionLineCommand command) {
        if (this.status == LineStatusEnum.STARTED || this.status == LineStatusEnum.PAUSED) {
            throw new IllegalStateException("无法注销运行中或暂停状态的产线，请先停止产线");
        }

        return ProductionLineRemovedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .build();
    }

    @Override
    public WorkstationAddedToLineEvent addWorkstation(AddWorkstationToLineCommand command, Workstation workstation) {
        // 校验产线状态
        if (this.status == LineStatusEnum.STARTED || this.status == LineStatusEnum.PAUSED) {
            throw new IllegalStateException("无法在运行或暂停状态下修改产线布局");
        }

        workstationIds.add(workstation.getWorkstationId());

        return WorkstationAddedToLineEvent.builder()
                .lineId(this.productionLineId.getValue())
                .workstationId(workstation.getWorkstationId().getValue())
                .previousWorkstationId(command.getPreviousWorkstationId())
                .build();
    }


    @Override
    public WorkstationRemovedFromLineEvent removeWorkstation(RemoveWorkstationFromLineCommand command, Workstation workstation) {
        // 校验产线状态
        if (this.status == LineStatusEnum.STARTED || this.status == LineStatusEnum.PAUSED) {
            throw new IllegalStateException("无法在运行或暂停状态下修改产线布局");
        }

        workstationIds.remove(workstation.getWorkstationId());

        return WorkstationRemovedFromLineEvent.builder()
                .lineId(this.productionLineId.getValue())
                .workstationId(workstation.getWorkstationId().getValue())
                .build();
    }


    @Override
    public ProductionLineReconfiguredEvent reconfigure(ReconfigureProductionLineCommand command) {
        // 记录原配置
        Long originalProcessRouteId = this.processRouteId;

        // 更新配置
        if (command.getNewProcessRouteId() != null) {
            this.processRouteId = command.getNewProcessRouteId();
        }

        // 生成事件
        return ProductionLineReconfiguredEvent.builder()
                .lineId(this.productionLineId.getValue())
                .originalProcessRouteId(originalProcessRouteId)
                .newProcessRouteId(command.getNewProcessRouteId())
                .build();
    }




    @Override
    public WorkOrderAssignedToLineEvent assignWorkOrder(AssignWorkOrderToLineCommand command, WorkOrder workOrder) {
        // 更新产线的工单列表
        if (assignedWorkOrderIds == null) {
            assignedWorkOrderIds = new ArrayList<>();
        }
        assignedWorkOrderIds.add(workOrder.getWorkOrderId().getValue());

        // 生成事件
        return WorkOrderAssignedToLineEvent.builder()
                .lineId(this.productionLineId.getValue())
                .workOrderId(workOrder.getWorkOrderId().getValue())
                .lineStatus(this.status.getKey())
                .build();
    }

    @Override
    public WorkOrderRemovedFromLineEvent removeWorkOrder(RemoveWorkOrderFromLineCommand command, WorkOrder workOrder) {
        // 从产线的工单列表中移除
        assignedWorkOrderIds.remove(workOrder.getWorkOrderId().getValue());

        // 生成事件
        return WorkOrderRemovedFromLineEvent.builder()
                .lineId(this.productionLineId.getValue())
                .workOrderId(workOrder.getWorkOrderId().getValue())
                .build();
    }


    @Override
    public ProductionLineCapacityUpdatedEvent updateCapacity(UpdateProductionLineCapacityCommand command) {

        // 生成事件
        return ProductionLineCapacityUpdatedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .lineStatus(this.status.getKey())
                .build();
    }


    @Override
    public ProductionLineAlarmTriggeredEvent reportAlarm(ReportProductionLineAlarmCommand command) {

        this.status = LineStatusEnum.FAULT;

        return ProductionLineAlarmTriggeredEvent.builder()
                .lineId(this.productionLineId.getValue())
                .lineStatus(this.status.getKey())
                .build();
    }

    @Override
    public ProductionLineFaultReportedEvent reportFault(ReportProductionLineFaultCommand command) {
        this.status = LineStatusEnum.FAULT;


        return ProductionLineFaultReportedEvent.builder()
                .lineId(this.productionLineId.getValue())
                .lineStatus(this.status.getKey())
                .build();
    }


    @Override
    public ProductionLineRecoveredEvent recover(RecoverProductionLineCommand command) {
//        fault.setResolved(true);
//        fault.setResolvedAt(LocalDateTime.now());
        this.status = LineStatusEnum.STARTED;

        // 构造领域事件
        return ProductionLineRecoveredEvent.builder()
                .lineId(this.productionLineId.getValue())
//                .faultId(fault.getId())
                .lineStatus(this.status.getKey())
                .build();
    }
}
